﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EITSurferInfinityLib.DataProcessing
{
    public static class IQDataProcessor2
    {
        public static double[] GetComplexImpedance(int[] I, int[] Q, PhysicalUnitParameter phy, double Frequency)
        {
           
            PhysicalUnitParameter phy2 = new PhysicalUnitParameter(phy.NSample, phy.FloatBits, phy.AnalogGain, phy.VRef, phy.CurrentA);
            double R1=560;
            double R2=2700;
            double C=270e-12;
            double filter= FilterAmplitude.LowPassAmplitude(Frequency, R1, C)*-4.6*1e-7*Frequency+1.09;
            phy2.AnalogGain = (R1 / R2)*filter;// 0.08 * FilterAmplitude.LowPassAmplitude(Frequency, 1000000);
            int fbit2 = phy.FloatBits + 0;
            if (fbit2 > 28)
            {
                fbit2 = 28;
            }
            phy2.FloatBits = fbit2;
            // phy2.NSample = 416;488.5 ( 560/ 2700.0) 1/11
            double[] Amplitude = GetAmplitude(I, Q, phy2);

            double[] result =new double[ Amplitude.Length];

            for (int i = 0; i < Amplitude.Length; i++)
            {
                result[i] = (Amplitude[i] / (phy2.CurrentA))*2; //times 2 because only measurement agains ground are made
                //  result[i] = Amplitude[i];
            }
            return result;
        }
        public static double[] GetPhase(int[] I, int[] Q, PhysicalUnitParameter phy)
        {
            int length = I.Length;
            double[] Phase = new double[length];
            for (int i = 0; i < length; i++)
            {
                double dI = I[i];
                double dQ = Q[i];

                Phase[i] = Math.Atan(dQ / dI)*180/Math.PI;// *phy2.VRef / (double)(phy2.NSample * Math.Pow(2, phy2.FloatBits) * phy2.AnalogGain);
            }
            return Phase;
        }
        public static double[] GetAmplitude(int[] I, int[] Q, PhysicalUnitParameter phy)
        {
            int length = I.Length;
            double[] Amplitude = new double[length];
            for (int i = 0; i < length; i++)
            {
                double dI = I[i];
                double dQ = Q[i];

                Amplitude[i] =2* Math.Sqrt(dI * dI + dQ * dQ) * phy.VRef/ (double)(phy.NSample * Math.Pow(2,phy.FloatBits)*phy.AnalogGain);
            }
            return Amplitude;
        }

        public static double[] GetAmplitude(int[,] IQ, PhysicalUnitParameter phy)
        {
            int length = IQ.GetLength(1);
            double[] Amplitude = new double[length];
            for (int i = 0; i < length; i++)
            {
                double dI = IQ[0,i];
                double dQ = IQ[1,i];

                Amplitude[i] = 2 * Math.Sqrt(dI * dI + dQ * dQ) * phy.VRef / (double)(phy.NSample * Math.Pow(2, phy.FloatBits) * phy.AnalogGain);
            }
            return Amplitude;
        }

        public static double[] GetAmplitude(int[] I, int[] Q, int NSamples)
        {
            int length = I.Length;
            double[] Amplitude = new double[length];
            for (int i = 0; i < length; i++)
            {
                double dI = I[i];
                double dQ = Q[i];

                Amplitude[i] = Math.Sqrt(dI * dI + dQ * dQ) / (double)(NSamples);
            }
            return Amplitude;
        }
        public static double[] GetAmplitude(int[] I, int[] Q)
        {
            int length = I.Length;
            double[] Amplitude = new double[length];
            for (int i = 0; i < length; i++)
            {
                double dI = I[i];
                double dQ = Q[i];

                Amplitude[i] =Math.Sqrt(dI*dI + dQ*dQ);
            }
            return Amplitude;
        }

        private static double GetPhysicalUnit(double d)
        {
            //double r = 0;
            //r=d*2*2*2.048 / (100.0*Math.Pow(2,18));
            

            return d;
        }

        public static double[] RemoveInjectionElectrode(double[] data, int offset, int numberElectrodes)
        {
            int NewDataLength;
            if (offset == ((numberElectrodes / 2) - 1))
            {
                NewDataLength = numberElectrodes * numberElectrodes-(numberElectrodes * 2);
            }
            else
            {
                NewDataLength = numberElectrodes * numberElectrodes - (numberElectrodes * 3);
            }

            double[] NewData = new double[NewDataLength];

            for (int i = 0, j = 0; i < data.Length; i++)
            {
                int rotation = (int)i / numberElectrodes;
                if (
                        !(
                        (i % numberElectrodes == (0 + rotation) % numberElectrodes) ||		 					/** Injection electrode */
                        (i % numberElectrodes == (offset + 1 + rotation) % numberElectrodes) ||					/** Reading electrode   */
                        (i % numberElectrodes == (numberElectrodes - offset - 1 + rotation) % numberElectrodes)	/** Oposite reading electrode */
                        )
                        )
                {
                    NewData[j] = data[i];
                    j++;
                }
            }

            return NewData;
        }

        public static double Sum(double [] d)
        {
            double sum=0;
            for (int i = 0; i < d.Length; i++)
            {
                sum += d[i];
            }
            return sum;
        }
        public static double Mean(double[] d)
        {
            return Sum(d)/d.Length;
        }
    }
}
